/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbRtbEng-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_26			*/
/*	File:		GlbRtbUtil.cpp			*/
/********************************************************/

#include "GlbRtbUtil.h"

extern CGlbRtbAdvs g_CAdvs;
extern CGlbRtbArea g_CArea;
extern GLBRTBCONF_S g_stConf;
extern GlbCls::CGlbRwLock g_CRwLock;

void GlbRtbUtilSig()
{
	signal(SIGINT, GlbRtbUtilQuit);
	signal(SIGSEGV, GlbRtbUtilQuit);
	signal(SIGTERM, GlbRtbUtilQuit);

	return;
}

void GlbRtbUtilQuit(int iSignal)
{
	GLB_ERROR("GlbRtbEng-1.0.0 stopped by signal %d\n", iSignal);

	exit(GLB_FAILURE);
}

int GlbRtbUtilConfLoad(char* pszConf)
{
	GlbCls::CGlbConf CConf;

	if (GLB_SUCCESS == CConf.GlbConfOpen(pszConf)) {
		/* dev */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_GLB, GLB_RU_DEV, g_stConf.m_szDev)) {
		}
		else {
			goto GlbError;
		}
		/* slp */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_GLB, GLB_RU_SLP, g_stConf.m_szSlp)) {
		}
		else {
			goto GlbError;
		}
		/* reds */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_CFG, GLB_RU_RDS, g_stConf.m_szReds)) {
		}
		else {
			goto GlbError;
		}
		/* rest */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_CFG, GLB_RU_RST, g_stConf.m_szRest)) {
		}
		else {
			goto GlbError;
		}
		/* advs */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_CFG, GLB_RU_ADV, g_stConf.m_szAdvs)) {
		}
		else {
			goto GlbError;
		}
		/* area */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_CFG, GLB_RU_ARE, g_stConf.m_szArea)) {
		}
		else {
			goto GlbError;
		}
		/* logs */
		if (GLB_SUCCESS == CConf.GlbConfGetVal(GLB_RU_CFG, GLB_RU_LOG, g_stConf.m_szLogs)) {
		}
		else {
			goto GlbError;
		}
		CConf.GlbConfClose();
	}
	else {
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;

GlbError:
	CConf.GlbConfClose();

	return GLB_FAILURE;
}

void GlbRtbUtilKernel()
{
	GlbIpcShmKernel(GLB_RU_SHM, GLB_RU_SHM);

	return;
}

void GlbRtbUtilConfShow()
{
	GLB_PRINT("DEV: %s\n", g_stConf.m_szDev);
	GLB_PRINT("SLP: %s\n", g_stConf.m_szSlp);
	GLB_PRINT("Reds: %s\n", g_stConf.m_szReds);
	GLB_PRINT("Rest: %s\n", g_stConf.m_szRest);
	GLB_PRINT("Advs: %s\n", g_stConf.m_szAdvs);
	GLB_PRINT("Area: %s\n", g_stConf.m_szArea);
	GLB_PRINT("Logs: %s\n", g_stConf.m_szLogs);

	return;
}

int GlbRtbUtilRwLockNew()
{
	int iReturn = GLB_SUCCESS;

	if (GLB_SUCCESS == (iReturn = g_CRwLock.GlbLockMalloc(NULL))) {
		iReturn = g_CRwLock.GlbLockCreate(false);
	}

	return iReturn;
}

void GlbRtbUtilRwLockDel()
{
	g_CRwLock.GlbLockDelete();

	return;
}

int GlbRtbUtilCreateAll()
{
	return GlbRtbUtilCreateAdvs() | GlbRtbUtilCreateArea();
}

int GlbRtbUtilCreateAdvs()
{
	int iReturn = GLB_SUCCESS;

	if (GLB_SUCCESS == g_CAdvs.GlbRtbBaseCreate(ftok(GLB_RA_PATH, GLB_RA_KEY), GLB_RA_SUM, GLB_RA_SIZE, GlbRtbAdvsComp)) {
		g_CAdvs.GlbRtbBaseReset(GLB_RA_SUM);
		if (GLB_SUCCESS == (iReturn = g_CAdvs.GlbRtbBaseInput((void*)g_stConf.m_szAdvs))) {
			iReturn = GlbRtbMemsCreate(g_CAdvs.GlbRtbBaseGetRef());
			GlbRtbIdxsAll(g_CAdvs.GlbRtbBaseGetRef());
			#ifdef _GLB_DEBUG_
				g_CAdvs.GlbRtbAdvsDisplay();
				GlbRtbMemsShow();
				GlbRtbIdxsShow();
			#endif
		}
	}
	else {
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int GlbRtbUtilCreateArea()
{
	int iReturn = GLB_SUCCESS;

	if (GLB_SUCCESS == g_CArea.GlbRtbBaseCreate(ftok(GLB_RR_PATH, GLB_RR_KEY), GLB_RR_SUM, GLB_RR_SIZE, NULL)) {
		g_CArea.GlbRtbBaseReset(GLB_RR_SUM);
		iReturn = g_CArea.GlbRtbBaseInput((void*)g_stConf.m_szArea);
	}
	else {
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

int GlbRtbUtilAttachAll()
{
	return GlbRtbUtilAttachAdvs() | GlbRtbUtilAttachArea();
}

int GlbRtbUtilAttachAdvs()
{
	if (GLB_SUCCESS == g_CAdvs.GlbRtbBaseCreate(ftok(GLB_RA_PATH, GLB_RA_KEY), GLB_RA_SUM, GLB_RA_SIZE, GlbRtbAdvsComp)) {
		g_CAdvs.GlbRtbBaseCount();
		GlbRtbIdxsAll(g_CAdvs.GlbRtbBaseGetRef());
		#ifdef _GLB_DEBUG_
			g_CAdvs.GlbRtbAdvsDisplay();
			GlbRtbIdxsShow();
		#endif
	}
	else {
		return GLB_FAILURE;
	}

	return GLB_SUCCESS;
}

int GlbRtbUtilAttachArea()
{

	return g_CArea.GlbRtbBaseCreate(ftok(GLB_RR_PATH, GLB_RR_KEY), GLB_RR_SUM, GLB_RR_SIZE, NULL);
}

int GlbRtbUtilUpdateAll()
{
	int iReturn = GLB_SUCCESS;

	#ifdef _GLB_DEBUG_
		GLB_PRINT("Will GlbRtbUtilUpdateAll ...\n");
	#endif
	g_CRwLock.GlbLockLock(GLB_RW_WRLK);
	iReturn = GlbRtbUtilCreateAdvs();
	g_CRwLock.GlbLockUnlock();

	return iReturn;
}

void GlbRtbUtilAdmin(char* pszHttp)
{
	int iLeng = 0;
	GlbCls::CGlbLog CFile;
	char* pszBody = pszHttp;
	char szFile[GLB_BYTE128] = {0};

	if (GLB_SUCCESS == strncasecmp(pszBody, GLB_RU_200, strlen(GLB_RU_200))) {
		if (NULL != (pszBody = strcasestr(pszBody, GLB_RU_CTL))) {
			iLeng = atoi(pszBody += strlen(GLB_RU_CTL));
			if (NULL != (pszBody = strstr(pszBody, GLB_RU_DRN))) {
				sprintf(szFile, "%s.tmp", g_stConf.m_szAdvs);
				if (GLB_SUCCESS == CFile.GlbLogOpen(szFile, GLB_LOG_WRITE)) {
					CFile.GlbLogWrite(pszBody + strlen(GLB_RU_DRN), iLeng);
					CFile.GlbLogClose();
					GlbRtbUtilCompare();
				}
				else {
					#ifdef _GLB_DEBUG_
						GLB_ERROR("Failed to GlbLogOpen\n");
					#endif
				}
			}
			else {
				#ifdef _GLB_DEBUG_
					GLB_ERROR("Failed to Content-Data\n");
				#endif
			}
		}
		else {
			#ifdef _GLB_DEBUG_
				GLB_ERROR("Failed to Content-Length\n");
			#endif
		}
	}
	else {
		#ifdef _GLB_DEBUG_
			GLB_ERROR("Failed to %s\n", GLB_RU_200);
		#endif
	}

	return;
}

void GlbRtbUtilCompare()
{
	int iSize = 0;
	bool bDo = false;
	struct stat stOld, stNew;
	GlbCls::CGlbFile COld, CNew;
	char szOld[GLB_BYTE128] = {0};
	char szNew[GLB_BYTE128] = {0};

	sprintf(szOld, "%s", g_stConf.m_szAdvs);
	sprintf(szNew, "%s.tmp", g_stConf.m_szAdvs);

	if (GLB_SUCCESS == stat(szOld, &stOld) && GLB_SUCCESS == stat(szNew, &stNew)) {
		if (stOld.st_size == stNew.st_size) {
			if (GLB_SUCCESS == COld.GlbFileOpen(szOld, GLB_O_RDONLY) && GLB_SUCCESS == CNew.GlbFileOpen(szNew, GLB_O_RDONLY)) {
				COld.GlbFileMmap(GLB_P_READ, GLB_M_PRIVATE, 0);
				CNew.GlbFileMmap(GLB_P_READ, GLB_M_PRIVATE, 0);
				iSize = COld.GlbFileGetSize() < CNew.GlbFileGetSize() ? COld.GlbFileGetSize() : CNew.GlbFileGetSize();
				if (GLB_SUCCESS != memcmp(COld.GlbFileGetFile(), CNew.GlbFileGetFile(), iSize)) {
					bDo = true;
				}
				COld.GlbFileMunmap(0);
				CNew.GlbFileMunmap(0);
				COld.GlbFileClose();
				CNew.GlbFileClose();
			}
		}
		else {
			bDo = true;
		}
	}
	else {
		#ifdef _GLB_DEBUG_
			GLB_ERROR("Failed to %s, %s\n", szOld, szNew);
		#endif
	}

	if (true == bDo) {
		rename(szNew, szOld);
		GlbRtbUtilUpdateAll();
	}
	else {
		remove(szNew);
	}

	return;
}

void GlbRtbUtilReqInput(GLBRTBREQ_S* pstReq, GlbNet::GLBPROKV_S* pstKv, USHORT usTotal)
{
	USHORT usCount = 0;

	for (usCount = 0; usCount < usTotal; usCount ++) {
		switch ((pstKv + usCount)->m_ucKey) {
			case GLB_RD_PBID:
				memcpy(pstReq->m_szBID, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			case GLB_RD_ADDR:
				memcpy(pstReq->m_szUIP, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			case GLB_RD_PPID:
				memcpy(pstReq->m_szPID, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			case GLB_RD_SIZE:
				memcpy(pstReq->m_szSiz, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			case GLB_RD_UAGT:
				memcpy(pstReq->m_szUag, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			case GLB_RD_UURL:
				memcpy(pstReq->m_szUrl, (pstKv + usCount)->m_puszValue, (pstKv + usCount)->m_iLength);
				break;
			default:
				break;
		}
	}

	return;
}

void GlbRtbUtilReqPrint(GLBRTBREQ_S* pstReq)
{
	GLB_PRINT("bid: %s\n", pstReq->m_szBID);
	GLB_PRINT("user ip: %s\n", pstReq->m_szUIP);
	GLB_PRINT("pid: %s\n", pstReq->m_szPID);
	GLB_PRINT("size: %s\n", pstReq->m_szSiz);
	GLB_PRINT("ua: %s\n", pstReq->m_szUag);
	GLB_PRINT("url: %s\n", pstReq->m_szUrl);

	return;
}

void GlbRtbUtilResInput(GLBRTBRES_S* pstRes, GlbNet::GLBPROKV_S* pstKv, USHORT* pusTotal)
{
	GLB_RU_SET(GLB_RD_PBID, pstRes->m_szBID);
	GLB_RU_SET(GLB_RD_ADDR, pstRes->m_szUIP);
	GLB_RU_SET(GLB_RD_PPID, pstRes->m_szPID);
	GLB_RU_SET(GLB_RD_SIZE, pstRes->m_szSiz);
	GLB_RU_SET(GLB_RD_ADID, pstRes->m_szAID);
	GLB_RU_SET(GLB_RD_MXCP, pstRes->m_szMcp);
	GLB_RU_SET(GLB_RD_SNPT, pstRes->m_szSnp);

	return;
}

void GlbRtbUtilResPrint(GLBRTBRES_S* pstRes)
{
	GLB_PRINT("aid: %s\n", pstRes->m_szAID);
	GLB_PRINT("bid: %s\n", pstRes->m_szBID);
	GLB_PRINT("user ip: %s\n", pstRes->m_szUIP);
	GLB_PRINT("pid: %s\n", pstRes->m_szPID);
	GLB_PRINT("size: %s\n", pstRes->m_szSiz);
	GLB_PRINT("max_cpm_price: %s\n", pstRes->m_szMcp);
	GLB_PRINT("html_snippet: %s\n", pstRes->m_szSnp);

	return;
}
